/*
 *  Copyright 2008 The MITRE Corporation (http://www.mitre.org/). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.mitre.lattice.graph;

import java.util.ArrayList;

import org.mitre.lattice.lattice.InvalidLatticeStructureException;
import org.mitre.lattice.lattice.LatticeNode;
import org.mitre.lattice.lattice.LatticeTree;
import org.mitre.mrald.util.Config;
import org.mitre.mrald.util.MraldError;
/**
 * Sample fitness function for the MakeChange example.
 */
public class SampleLattices
{

    public static LatticeTree buildNewLattice() throws InvalidLatticeStructureException
    {

        LatticeTree ret = new LatticeTree();
        LatticeNode root = ret.getRootNode();
        ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
        rootArray.add(root);

        root.addParents(new ArrayList());

    return ret;
      }

    public static LatticeTree buildVeryVeryComplexDiamondLattice()
    {
      try
      {
        LatticeTree ret = new LatticeTree();
        LatticeNode root = ret.getRootNode();
        ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
        rootArray.add(root);

    LatticeNode brp = Config.getLatticeFactory().createNode("bottomRightPoint");
        ArrayList<LatticeNode> bottomRightPoint = new ArrayList<LatticeNode>();
        bottomRightPoint.add(brp);
        root.addParents(bottomRightPoint);
        brp.addChildren(rootArray);

        LatticeNode rp = Config.getLatticeFactory().createNode("rightPoint");
        ArrayList<LatticeNode> rightPoint = new ArrayList<LatticeNode>();
        rightPoint.add(rp);
        root.addParents(rightPoint);
        rp.addChildren(rootArray);

        LatticeNode lp = Config.getLatticeFactory().createNode("leftPoint");
        ArrayList<LatticeNode> leftPoint = new ArrayList<LatticeNode>();
    leftPoint.add(lp);
        root.addParents(leftPoint);
        lp.addChildren(rootArray);

    LatticeNode blp = Config.getLatticeFactory().createNode("bottomLeftPoint");
        ArrayList<LatticeNode> bottomLeftPoint = new ArrayList<LatticeNode>();
        bottomLeftPoint.add(blp);
        root.addParents(bottomLeftPoint);
        blp.addChildren(rootArray);

    LatticeNode cp = Config.getLatticeFactory().createNode("centerPoint");
        ArrayList<LatticeNode> centerPoint = new ArrayList<LatticeNode>();
    centerPoint.add(cp);
        root.addParents(centerPoint);
        cp.addChildren(rootArray);

    LatticeNode emlp  = Config.getLatticeFactory().createNode("extremeMidLeftPoint");
        ArrayList<LatticeNode> extremeMidLeftPoint = new ArrayList<LatticeNode>();
    extremeMidLeftPoint.add( emlp );

    LatticeNode emrp  = Config.getLatticeFactory().createNode("extremeMidRightPoint");
        ArrayList<LatticeNode> extremeMidRightPoint = new ArrayList<LatticeNode>();
    extremeMidRightPoint.add( emrp );

    LatticeNode mlp  = Config.getLatticeFactory().createNode("midLeftPoint");
        ArrayList<LatticeNode> midLeftPoint = new ArrayList<LatticeNode>();
    midLeftPoint.add( mlp );

    LatticeNode mcp  = Config.getLatticeFactory().createNode("midCenterPoint");
        ArrayList<LatticeNode> midCenterPoint = new ArrayList<LatticeNode>();
    midCenterPoint.add( mcp );

    LatticeNode mrp  = Config.getLatticeFactory().createNode("midRightPoint");
        ArrayList<LatticeNode> midRightPoint = new ArrayList<LatticeNode>();
    midRightPoint.add( mrp );

      LatticeNode tlp  = Config.getLatticeFactory().createNode("topLeftPoint");
        ArrayList<LatticeNode> topLeftPoint = new ArrayList<LatticeNode>();
    topLeftPoint.add( tlp );

    LatticeNode tcp  = Config.getLatticeFactory().createNode("topCenterPoint");
        ArrayList<LatticeNode> topCenterPoint = new ArrayList<LatticeNode>();
    topCenterPoint.add( tcp );

    LatticeNode trp  = Config.getLatticeFactory().createNode("topRightPoint");
        ArrayList<LatticeNode> topRightPoint = new ArrayList<LatticeNode>();
    topRightPoint.add( trp );

    LatticeNode terp  = Config.getLatticeFactory().createNode("topExtremeRightPoint");
        ArrayList<LatticeNode> topExtremeRightPoint = new ArrayList<LatticeNode>();
    topExtremeRightPoint.add( terp );

    LatticeNode telp  = Config.getLatticeFactory().createNode("topExtremeLeftPoint");
        ArrayList<LatticeNode> topExtremeLeftPoint = new ArrayList<LatticeNode>();
    topExtremeLeftPoint.add( telp );

    LatticeNode teerp  = Config.getLatticeFactory().createNode("topExtremeExtremeRightPoint");
        ArrayList<LatticeNode> topExtremeExtremeRightPoint = new ArrayList<LatticeNode>();
    topExtremeExtremeRightPoint.add( teerp );

    LatticeNode tp  = Config.getLatticeFactory().createNode("topPoint");
        ArrayList<LatticeNode> topPoint = new ArrayList<LatticeNode>();
    topPoint.add( tp );

    blp.addParents(topExtremeLeftPoint);
        blp.addParents(extremeMidLeftPoint);

    lp.addParents(extremeMidLeftPoint);
        lp.addParents(midLeftPoint);

        cp.addParents(midLeftPoint);
        cp.addParents(midCenterPoint);
    cp.addParents(midLeftPoint);

        rp.addParents(topExtremeRightPoint);
        rp.addParents(midRightPoint);

    brp.addParents(extremeMidRightPoint);
        brp.addParents(midRightPoint);

        emlp.addParents(topLeftPoint);

    mlp.addParents(topLeftPoint);
    mlp.addParents(topCenterPoint);
        //mlp.addParents(topExtremeRightPoint);

        mcp.addParents(topRightPoint);
    mcp.addParents(topCenterPoint);

    //mrp.addParents(midCenterPoint);

    emrp.addParents(topExtremeRightPoint);
        emrp.addParents(topExtremeExtremeRightPoint);

    terp.addParents(topPoint);
    teerp.addParents(topPoint);
    tlp.addParents(topPoint);
    trp.addParents(topPoint);
    tcp.addParents(topPoint);
    telp.addParents(topPoint);

    for (int i=0; i < blp.countParentNodes(); i++)
    {
        LatticeNode parentNode = blp.getParents().get(i);
        parentNode.addChildren(bottomLeftPoint);

    }

    for (int i=0; i < lp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (lp.getParents().get(i));
        parentNode.addChildren(leftPoint);

    }

    for (int i=0; i < cp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (cp.getParents().get(i));
        parentNode.addChildren(centerPoint);
    }

    for (int i=0; i < rp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (rp.getParents().get(i));
        parentNode.addChildren(rightPoint);
    }

    for (int i=0; i < brp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (brp.getParents().get(i));
        parentNode.addChildren(bottomRightPoint);
    }

    for (int i=0; i < emlp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (emlp.getParents().get(i));
        parentNode.addChildren(extremeMidLeftPoint);
    }

    for (int i=0; i < mlp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mlp.getParents().get(i));
        parentNode.addChildren(midLeftPoint);

    }

    for (int i=0; i < mcp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mcp.getParents().get(i));
        parentNode.addChildren(midCenterPoint);

    }

    for (int i=0; i < mrp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mrp.getParents().get(i));
        parentNode.addChildren(midRightPoint);

    }

    for (int i=0; i < emrp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (emrp.getParents().get(i));
        parentNode.addChildren(extremeMidRightPoint);
    }

    for (int i=0; i < terp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (terp.getParents().get(i));
        parentNode.addChildren(topExtremeRightPoint);
    }

    for (int i=0; i < teerp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (teerp.getParents().get(i));
        parentNode.addChildren(topExtremeExtremeRightPoint);
    }

    for (int i=0; i < tlp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (tlp.getParents().get(i));
        parentNode.addChildren(topLeftPoint);
    }

    for (int i=0; i < trp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (trp.getParents().get(i));
        parentNode.addChildren(topRightPoint);
    }

    for (int i=0; i < tcp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (tcp.getParents().get(i));
        parentNode.addChildren(topCenterPoint);
    }

    for (int i=0; i < telp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (telp.getParents().get(i));
        parentNode.addChildren(topExtremeLeftPoint);
    }
     //tp.addChildren(topCenterPoint);
     //tcp.addParents(topPoint);

        return ret;
      }
      catch(Exception e)
      {
          e.printStackTrace();
         return null;
      }
    }

    /*
    A complex lattice shape following the design below
            *T
    *TL	*TC	*TR
    *L	*C	*R
        *Root

    T:	Top
    TL: 	Top Left
    TC:	Top Center
    TR:	Top Right
    L:	Left
    C: 	Center
    R:	Right
    */
    public static LatticeTree buildVeryComplexDiamondLattice()
    {
      try
      {
        LatticeTree ret = new LatticeTree();
        LatticeNode root = ret.getRootNode();
        ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
        rootArray.add(root);

        LatticeNode rp = Config.getLatticeFactory().createNode("rightPoint");
        ArrayList<LatticeNode> rightPoint = new ArrayList<LatticeNode>();
        rightPoint.add(rp);
        root.addParents(rightPoint);
        rp.addChildren(rootArray);

        LatticeNode lp = Config.getLatticeFactory().createNode("leftPoint");
        ArrayList<LatticeNode> leftPoint = new ArrayList<LatticeNode>();
    leftPoint.add(lp);
        root.addParents(leftPoint);
        lp.addChildren(rootArray);

    LatticeNode cp = Config.getLatticeFactory().createNode("centerPoint");
        ArrayList<LatticeNode> centerPoint = new ArrayList<LatticeNode>();
    centerPoint.add(cp);
        root.addParents(centerPoint);
        cp.addChildren(rootArray);

        LatticeNode tlp  = Config.getLatticeFactory().createNode("topLeftPoint");
        ArrayList<LatticeNode> topLeftPoint = new ArrayList<LatticeNode>();
    topLeftPoint.add( tlp );

    LatticeNode tcp  = Config.getLatticeFactory().createNode("topCenterPoint");
        ArrayList<LatticeNode> topCenterPoint = new ArrayList<LatticeNode>();
    topCenterPoint.add( tcp );

    LatticeNode trp  = Config.getLatticeFactory().createNode("topRightPoint");
        ArrayList<LatticeNode> topRightPoint = new ArrayList<LatticeNode>();
    topRightPoint.add( trp );

    LatticeNode mlp  = Config.getLatticeFactory().createNode("midLeftPoint");
        ArrayList<LatticeNode> midLeftPoint = new ArrayList<LatticeNode>();
    midLeftPoint.add( mlp );

    LatticeNode mcp  = Config.getLatticeFactory().createNode("midCenterPoint");
        ArrayList<LatticeNode> midCenterPoint = new ArrayList<LatticeNode>();
    midCenterPoint.add( mcp );

    LatticeNode tp  = Config.getLatticeFactory().createNode("topPoint");
        ArrayList<LatticeNode> topPoint = new ArrayList<LatticeNode>();
    topPoint.add( tp );

        cp.addParents(midLeftPoint);
        cp.addParents(midCenterPoint);

    mcp.addParents(topLeftPoint);
        mcp.addParents(topRightPoint);
    mcp.addParents(topCenterPoint);

    mlp.addParents(topLeftPoint);
        mlp.addParents(topRightPoint);
    mlp.addParents(topCenterPoint);

    lp.addParents(midLeftPoint);
        lp.addParents(midCenterPoint);

        rp.addParents(topRightPoint);
        rp.addParents(midCenterPoint);

    for (int i=0; i < mlp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mlp.getParents().get(i));
        parentNode.addChildren(midLeftPoint);

    }

    for (int i=0; i < mcp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mcp.getParents().get(i));
        parentNode.addChildren(midCenterPoint);

    }

    for (int i=0; i < cp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (cp.getParents().get(i));
        parentNode.addChildren(centerPoint);

    }


        for (int i=0; i < lp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (lp.getParents().get(i));
        parentNode.addChildren(leftPoint);

    }

    for (int i=0; i < rp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (rp.getParents().get(i));
        parentNode.addChildren(rightPoint);

    }
        tp.addChildren(topCenterPoint);
    tcp.addParents(topPoint);

        return ret;
        }catch(Exception e)
        {
            throw new MraldError(e);
        }


    }

     /*
    A complex lattice shape following the design below
            *T
    *TL	*TC	*TR
    *L	*C	*R
        *Root

    T:	Top
    TL: 	Top Left
    TC:	Top Center
    TR:	Top Right
    L:	Left
    C: 	Center
    R:	Right
    */
    public static LatticeTree buildComplexDiamondLattice()
    {
      try
      {
        LatticeTree ret = new LatticeTree();
        LatticeNode root = ret.getRootNode();
        ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
        rootArray.add(root);

        LatticeNode rp = Config.getLatticeFactory().createNode("rightPoint");
        ArrayList<LatticeNode> rightPoint = new ArrayList<LatticeNode>();
        rightPoint.add(rp);
        root.addParents(rightPoint);
        rp.addChildren(rootArray);

        LatticeNode lp = Config.getLatticeFactory().createNode("leftPoint");
        ArrayList<LatticeNode> leftPoint = new ArrayList<LatticeNode>();
    leftPoint.add(lp);
        root.addParents(leftPoint);
        lp.addChildren(rootArray);

    LatticeNode cp = Config.getLatticeFactory().createNode("centerPoint");
        ArrayList<LatticeNode> centerPoint = new ArrayList<LatticeNode>();
    centerPoint.add(cp);
        root.addParents(centerPoint);
        cp.addChildren(rootArray);

        LatticeNode tlp  = Config.getLatticeFactory().createNode("topLeftPoint");
        ArrayList<LatticeNode> topLeftPoint = new ArrayList<LatticeNode>();
    topLeftPoint.add( tlp );

    LatticeNode tcp  = Config.getLatticeFactory().createNode("topCenterPoint");
        ArrayList<LatticeNode> topCenterPoint = new ArrayList<LatticeNode>();
    topCenterPoint.add( tcp );

    LatticeNode trp  = Config.getLatticeFactory().createNode("topRightPoint");
        ArrayList<LatticeNode> topRightPoint = new ArrayList<LatticeNode>();
    topRightPoint.add( trp );

    LatticeNode tp  = Config.getLatticeFactory().createNode("topPoint");
        ArrayList<LatticeNode> topPoint = new ArrayList<LatticeNode>();
    topPoint.add( tp );

        cp.addParents(topLeftPoint);
        cp.addParents(topRightPoint);
    cp.addParents(topCenterPoint);

    for (int i=0; i < cp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (cp.getParents().get(i));
        parentNode.addChildren(centerPoint);

    }

        lp.addParents(topLeftPoint);
        lp.addParents(topCenterPoint);

        for (int i=0; i < lp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (lp.getParents().get(i));
        parentNode.addChildren(leftPoint);

    }

        rp.addParents(topRightPoint);
        rp.addParents(topCenterPoint);

    for (int i=0; i < lp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (rp.getParents().get(i));
        parentNode.addChildren(rightPoint);

    }
        tp.addChildren(topCenterPoint);
    tcp.addParents(topPoint);

        return ret;
      }
      catch(Exception e)
      {
        return null;
      }

    }

    public static LatticeTree buildDiamondLattice()
    {
      try
      {
       LatticeTree ret = new LatticeTree();
       LatticeNode root =ret.getRootNode();
       ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
       rootArray.add(  root );
       LatticeNode rp = Config.getLatticeFactory().createNode("rightPoint");

       ArrayList<LatticeNode> rightPoint = new ArrayList<LatticeNode>();
       rightPoint.add(rp);

       root.addParents(rightPoint);
       rp.addChildren(rootArray);

       LatticeNode lp = Config.getLatticeFactory().createNode("leftPoint");

       ArrayList<LatticeNode> leftPoint = new ArrayList<LatticeNode>();
       leftPoint.add(lp);

       root.addParents(leftPoint);
       lp.addChildren(rootArray);

       LatticeNode tp = Config.getLatticeFactory().createNode("topPoint");

       ArrayList<LatticeNode> topPoint = new ArrayList<LatticeNode>();
       topPoint.add(tp);

       rp.addParents(topPoint);
       lp.addParents(topPoint);

       tp.addChildren(rightPoint);
       tp.addChildren(leftPoint);
       return ret;
        }catch(Exception e)
        {
            throw new MraldError(e);
        }

    }

    /*
    A complex lattice shape following the design below
            *T
    *TL	*TC	*TR
    *L	*C	*R
        *Root

    T:	Top
    TL: 	Top Left
    TC:	Top Center
    TR:	Top Right
    L:	Left
    C: 	Center
    R:	Right
    */
    public static LatticeTree buildSimpleDiamondLattice()
    {
       try
       {
        LatticeTree ret = new LatticeTree();
        LatticeNode root = ret.getRootNode();
        ArrayList<LatticeNode> rootArray = new ArrayList<LatticeNode>();
        rootArray.add(root);

        LatticeNode rp = Config.getLatticeFactory().createNode("rightPoint");
        ArrayList<LatticeNode> rightPoint = new ArrayList<LatticeNode>();
        rightPoint.add(rp);
        root.addParents(rightPoint);
        rp.addChildren(rootArray);

    LatticeNode erp = Config.getLatticeFactory().createNode("extremeRightPoint");
        ArrayList<LatticeNode> extremeRightPoint = new ArrayList<LatticeNode>();
        extremeRightPoint.add(erp);
        root.addParents(extremeRightPoint);
        erp.addChildren(rootArray);

        LatticeNode lp = Config.getLatticeFactory().createNode("leftPoint");
        ArrayList<LatticeNode> leftPoint = new ArrayList<LatticeNode>();
    leftPoint.add(lp);
        root.addParents(leftPoint);
        lp.addChildren(rootArray);

    LatticeNode mlp  = Config.getLatticeFactory().createNode("midLeftPoint");
        ArrayList<LatticeNode> midLeftPoint = new ArrayList<LatticeNode>();
    midLeftPoint.add( mlp );

        LatticeNode tlp  = Config.getLatticeFactory().createNode("topLeftPoint");
        ArrayList<LatticeNode> topLeftPoint = new ArrayList<LatticeNode>();
    topLeftPoint.add( tlp );

    LatticeNode tclp  = Config.getLatticeFactory().createNode("topCenterLeftPoint");
        ArrayList<LatticeNode> topCenterLeftPoint = new ArrayList<LatticeNode>();
    topCenterLeftPoint.add( tclp );

    LatticeNode tcrp  = Config.getLatticeFactory().createNode("topCenterRightPoint");
        ArrayList<LatticeNode> topCenterRightPoint = new ArrayList<LatticeNode>();
    topCenterRightPoint.add( tcrp );

    LatticeNode trp  = Config.getLatticeFactory().createNode("topRightPoint");
        ArrayList<LatticeNode> topRightPoint = new ArrayList<LatticeNode>();
    topRightPoint.add( trp );

        lp.addParents(midLeftPoint);
        lp.addParents(topCenterRightPoint);

        for (int i=0; i < lp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (lp.getParents().get(i));
        parentNode.addChildren(leftPoint);

    }

        rp.addParents(topRightPoint);

    for (int i=0; i < rp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (rp.getParents().get(i));
        parentNode.addChildren(rightPoint);

    }

    mlp.addParents(topLeftPoint);
    mlp.addParents(topCenterLeftPoint);

    for (int i=0; i < mlp.countParentNodes(); i++)
    {
        LatticeNode parentNode = (mlp.getParents().get(i));
        parentNode.addChildren(midLeftPoint);

    }

        return ret;
        }catch(Exception e)
        {
            throw new MraldError(e);
        }

    }
}
